import os
import shutil
import sys
import time
from concurrent.futures import ThreadPoolExecutor
from inspect import currentframe, stack, getmodule


class log:
    def __init__(self):
        self._pool_ = ThreadPoolExecutor(max_workers=os.cpu_count() * 2)
        self.len = 0
        self.diskIdentifier = False
        if not os.path.isdir("./log"):
            os.mkdir("./log")

    def _ioTask_(self, level, pid, filePath, line, msg):
        text = f"{time.strftime('%H:%M:%S', time.localtime())}  pid:{pid}  {level}  file-path:{os.path.relpath(filePath)}  line:{line}  {msg}\n"
        print(text)
        if not os.path.isfile(address := f"./log/{time.strftime('%Y-%m-%d', time.localtime())}.log"):
            f = open(address, mode="w", encoding="utf-8", buffering=-1)
            f.write(text)
            f.close()
        else:
            f = open(address, mode="a", encoding="utf-8", buffering=-1)
            f.write(text)
            f.close()
        if not self.diskIdentifier:
            self._test_()
        self.len -= 1

    def _test_(self):
        if sys.platform.startswith('linux'):
            if (shutil.disk_usage("/")[2] / 2048) < 5:
                self.Critical("系统磁盘空间不足 5MB 无法维持运行", getmodule(stack()[1][0]).__file__,
                              str(currentframe().f_back.f_lineno))
                self.diskIdentifier = True
        elif sys.platform.startswith('win'):
            if (shutil.disk_usage(os.getcwd().split("\\")[0])[2] / 2048) < 5:
                self.Critical("系统磁盘空间不足 5MB 无法维持运行", getmodule(stack()[1][0]).__file__,
                              str(currentframe().f_back.f_lineno))
                self.diskIdentifier = True

    def error(self, msg, path, line, pid):
        self._addLen_()
        self._pool_.submit(
            self._ioTask_, "Error", pid, path, line, msg)

    def warn(self, msg, path, line, pid):
        self._addLen_()
        self._pool_.submit(
            self._ioTask_, "Warn", pid, path, line, msg)

    def info(self, msg, path, line, pid):
        self._addLen_()
        self._pool_.submit(
            self._ioTask_, "Info",  pid, path, line, msg)

    def Critical(self, msg, path, line, pid):
        self._addLen_()
        self._pool_.submit(
            self._ioTask_, "Critical",  pid, path, line, msg)

    def _addLen_(self):
        self.len += 1

    def __len__(self):
        return self.len
